<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<script>
  function asyncFunc () {}

  function toRawType (target) {
    return Object.prototype.toString.call(target)
  }

  function getType (target) {
    return toRawType(target).slice(8, -1).toLowerCase()
  }

  console.log(asyncFunc.toString())
  console.log([asyncFunc])

  async function xxxxx() {
    console.log(await getType('vvvvv'))
  }

  function compose (...arg) {
    return (arg || []).reduce(async (prev, next) => {
      return async (args, cb, __next) => await prev(args, cb, async () => await next(args, cb, __next))
    })
  }

  function func_01 (data, cb, next) {
    console.log(1, data, cb, next)

    next()
  }

  async function func_02 (data, cb, next) {
    const exec =  await compose(func_03, func_04)


    console.log(2, data, cb, next)
    console.log(2, await exec(data, cb))
  }

  async function func_03 (data, cb, next) {
    console.log(3, data, cb, next)

    return 'vvvvv'
  }

  function func_04 (data, cb, next) {
    console.log(4, data, cb, next)
  }

  async function runFunc () {
    const exec = await compose(func_01, func_02)

    console.log(exec)
    exec('xxxxxx', () => {})
  }

  runFunc ()
</script>
</body>
</html>